package org.webrtc.ui;

import java.util.LinkedList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.json.JSONException;
import org.json.JSONObject;
import org.webrtc.AudioTrack;
import org.webrtc.DataChannel;
import org.webrtc.IceCandidate;
import org.webrtc.MediaConstraints;
import org.webrtc.MediaConstraints.KeyValuePair;
import org.webrtc.MediaStream;
import org.webrtc.PeerConnection;
import org.webrtc.PeerConnectionFactory;
import org.webrtc.SdpObserver;
import org.webrtc.SessionDescription;
import org.webrtc.StatsObserver;
import org.webrtc.StatsReport;
import org.webrtc.VideoCapturer;
import org.webrtc.VideoRenderer;
import org.webrtc.VideoRenderer.I420Frame;
import org.webrtc.VideoSource;
import org.webrtc.VideoTrack;
import org.webrtc.mqttclientsample.ISocketClient;
import org.webrtc.mqttclientsample.LogUtis;
import org.webrtc.mqttclientsample.Message;
import org.webrtc.mqttclientsample.MessageService;
import org.webrtc.mqttclientsample.ZZConfig;
import org.webrtc.ui.AudioUtil.OnAudioChangeListener;
import org.webrtc.ui.CallTimer.TimeContext;
import org.webrtc.videoengine.ViERenderer;

import com.bieyang.anjia.R;
import com.bieyang.anjia.ui.activity.BaseActivity;
import com.bieyang.anjia.utils.Constants;
import com.bieyang.anjia.utils.HomeWatcherReceiver;
import com.bieyang.anjia.utils.Show;

import de.greenrobot.event.EventBus;
import android.app.Activity;
import android.app.KeyguardManager;
import android.app.NotificationManager;
import android.app.KeyguardManager.KeyguardLock;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.res.Configuration;
import android.graphics.Point;
import android.graphics.drawable.Drawable;
import android.hardware.Camera;
import android.media.AudioManager;
import android.net.Uri;
import android.os.Build;
import android.os.Build.VERSION;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
import android.os.PowerManager;
import android.telephony.TelephonyManager;
import android.util.Log;
import android.view.Gravity;
import android.view.MotionEvent;
import android.view.Surface;
import android.view.SurfaceView;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.View.OnTouchListener;
import android.view.ViewStub;
import android.view.Window;
import android.view.WindowManager;
import android.widget.Button;
import android.widget.FrameLayout;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.RelativeLayout;
import android.widget.TextView;
import android.widget.Toast;

/**
 * 视频通话界面，主机监控机公用，主要功能有开启关闭视频，开启关闭声音
 * 
 * @author Administrator
 * 
 */
public class VideoUI extends BaseActivity implements OnClickListener,
		OnAudioChangeListener, TimeContext {
	public static final String INTENT_EXTRA_JID = "jid";
	public static final String INTENT_EXTRA_ISCALLER = "isCaller";
	public static final String INTENT_EXTRA_NAME = "DisplayName";
	public static final String INTENT_EXTRA_MESSAGE_URL = "message";
	public static final String INTENT_EXTRA_TYPE = "type";
	public static final String INTENT_EXTRA_SESSIONID = "sessionid";
	private static final String TAG = "VideoUI";
	private PeerConnectionFactory factory;
	private VideoSource videoSource;
	private PeerConnection pc;
	private final PCObserver pcObserver = new PCObserver();
	private final SDPObserver sdpObserver = new SDPObserver();
	private final GAEChannelClient.MessageHandler gaeHandler = new GAEHandler();

	private VideoStreamsView vsv;
	private LinkedList<IceCandidate> queuedRemoteCandidates = new LinkedList<IceCandidate>();
	private List<PeerConnection.IceServer> iceServers = new LinkedList<PeerConnection.IceServer>();
	private MediaConstraints pcConstraints = new MediaConstraints();
	private MediaConstraints videoConstraints = new MediaConstraints();

	private final Boolean[] quit = new Boolean[] { false };
	private MediaConstraints sdpMediaConstraints;
	private PowerManager.WakeLock wakeLock;

	private String mUid;
	private String mDisplayName;
	private boolean isInit;
	private boolean mIsCaller;

	public final int UA_STATE_IDLE = 0;
	public final int UA_STATE_INCOMING_CALL = 1;
	public final int UA_STATE_OUTGOING_CALL = 2;
	public final int UA_STATE_INCALL = 3;
	public final int UA_STATE_HOLD = 4;
	public final int UA_STATE_REJECT = 6;
	public final int UA_STATTE_DROP = 5;

	public int call_state = UA_STATE_IDLE;

	// private HisuperAvatarManager mAvatarManagert;

	private KeyguardManager mKManager;
	private KeyguardLock mKeyguardLock;

	private WakeLockUtil mWakeLockUtil;
	private AudioUtil mAudioUtil;

	private boolean isAudioOpen = false; // 默认为打开声音（监控机）； 默认关闭声音,按下时同时打开2边的的声音

	private BroadcastReceiver receiver = new BroadcastReceiver() {

		@Override
		public void onReceive(Context context, Intent intent) {
			// TODO Auto-generated method stub
			VideoUI.this.finish();
		}
	};
	private long callStartTime;
	// private CallTimer mCallTimer;

	private ImageView mIv_caller, mNetworkState, imgBlack;
	private TextView mtv_NetworkState, mCalleeName, mtitle;

	private RelativeLayout mRl_videopanel, mRl_phoneCallingpanel;
	private LinearLayout mLl_phoneComeingPanel, mll_audioCallFram;
	private Point displaySize;

	private TextView mBtn_accept, mBtn_reject;
	private TextView mBtn_speaker, mBtn_mute, mBtn_back, mBtn_phone_end,
			mSwitchCamare, mVideoClose;

	private Button mAudioClose, mBtn_end;
	private SurfaceView mLocalView;
	private FrameLayout mLayout_call;
	private TextView mCallState;
	private boolean mIsvideo;
	private boolean isFrontCamare;
	private boolean isVideoOpen;

	MediaStream lMS;
	Window window;

	private NotificationManager mNotificationManager;
	private int NOTIFY_ID = 1000000;

	private Handler mHandler = new Handler();

	private static final int SHOW_AUDIO = 10003;
	private ISocketClient mClient;

	/*
	 * 视频接通后3s再显示功能按钮（声音开启关闭按钮，默认为声音关闭）
	 */
	private Handler uiHandler = new Handler() {
		public void handleMessage(android.os.Message msg) {
			switch (msg.what) {
			case SHOW_AUDIO:

				// mAudioClose.setVisibility(View.VISIBLE);
				if (isAudioOpen) {
					mAudioClose.setBackgroundResource(R.drawable.sound);
				} else {
					mAudioClose.setBackgroundResource(R.drawable.sound_p);
				}

				break;

			default:
				break;
			}
		};
	};

	public long getCallStartTime() {
		return callStartTime;
	}

	public void setCallStartTime(long callStartTime) {
		this.callStartTime = callStartTime;
	}

	public void startCallerRingtone(AudioUtil audioUtil) {

		String packageName = this.getPackageName();
		Uri uri = Uri.parse("android.resource://" + packageName + "/"
				+ R.raw.ringback);
		audioUtil.setUri(uri);
		audioUtil.play();

	}

	/**
	 * 启动电话拨打
	 * 
	 * @param context
	 * @param jid
	 *            被叫id
	 * @param name
	 *            被叫昵称
	 * @param isVideo
	 * @param isCaller
	 *            是否是主叫
	 * @param newTask
	 */
	public static void Lauch(Context context, String jid, String name,
			boolean isVideo, boolean isCaller, boolean newTask) {
		Intent intent = new Intent(context, VideoUI.class);
		intent.putExtra(INTENT_EXTRA_JID, jid);
		intent.putExtra(INTENT_EXTRA_NAME, name);
		intent.putExtra(INTENT_EXTRA_TYPE, isVideo);
		intent.putExtra(INTENT_EXTRA_ISCALLER, isCaller);
		if (newTask)
			intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
		context.startActivity(intent);
	}

	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);

		registerEvent();
		registerBroadcast();
		Thread.setDefaultUncaughtExceptionHandler(new UnhandledExceptionHandler(
				this));

		getWindow().addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);
		getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);

		setContentView(R.layout.audio_call);

		bindService();

		mNotificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);

		mAudioUtil = new AudioUtil(this, this);

		Intent mIntent = getIntent();
		mUid = getIntent().getStringExtra(INTENT_EXTRA_JID);
		mIsCaller = mIntent.getBooleanExtra(INTENT_EXTRA_ISCALLER, false);
		mDisplayName = mIntent.getStringExtra(INTENT_EXTRA_NAME);
		mIsvideo = mIntent.getBooleanExtra(INTENT_EXTRA_TYPE, false);
		initChildView();

		if (!mIsvideo)
			mWakeLockUtil = new WakeLockUtil(this);
		if (mIsCaller) {
			// isAudioOpen=false; //如果是主叫，默认关闭声音
			// mRl_phoneCallingpanel.setVisibility(View.VISIBLE);
			if (mIsvideo) {
				mLl_phoneComeingPanel.setVisibility(View.GONE);
				mRl_videopanel.setVisibility(View.VISIBLE);
				mRl_phoneCallingpanel.setVisibility(View.GONE);
			} else {
				mRl_videopanel.setVisibility(View.GONE);
				mRl_phoneCallingpanel.setVisibility(View.VISIBLE);
			}

		} else {
			imgBlack.setVisibility(View.VISIBLE); // new black coming
			mRl_videopanel.setVisibility(View.GONE);
			mRl_phoneCallingpanel.setVisibility(View.GONE);
			mLl_phoneComeingPanel.setVisibility(View.GONE);// VISIBLE

			call_state = UA_STATE_INCOMING_CALL;

		}

		// mCalleeName.setText(mDisplayName); //modify new

		displaySize = new Point();
		int w = getWindowManager().getDefaultDisplay().getWidth();
		int h = getWindowManager().getDefaultDisplay().getHeight();
		displaySize.set(w, h);

		abortUnless(PeerConnectionFactory.initializeAndroidGlobals(this),
				"Failed to initializeAndroidGlobals");

		sdpMediaConstraints = new MediaConstraints();
		sdpMediaConstraints.mandatory.add(new MediaConstraints.KeyValuePair(
				"OfferToReceiveAudio", "true"));
		sdpMediaConstraints.mandatory.add(new MediaConstraints.KeyValuePair(
				"OfferToReceiveVideo", mIsvideo ? "true" : "false"));
		pcConstraints.optional.add(new KeyValuePair("DtlsSrtpKeyAgreement",
				"true"));
		// new PeerConnection.IceServer("stun:stunserver.org:3478");
		PeerConnection.IceServer turns = new PeerConnection.IceServer(
				ZZConfig.turnWebUrl, "test1", "1234");

		iceServers.add(turns);

		setVolumeControlStream(AudioManager.STREAM_VOICE_CALL);

		openLock();
		isVideoOpen = true;

		Show.toast(VideoUI.this, R.string.tip_videoui);
	}

	/**
	 * 横屏时，去掉标题栏即可,暂不支持，横竖屏切换了图像就没了
	 */

	private void initChildView() {
		imgBlack = (ImageView) findViewById(R.id.imgBlack);
		mtitle = (TextView) findViewById(R.id.voip_title_textview);
		if (mIsvideo)
			mtitle.setText(mDisplayName);
		// mtitle.setText(R.string.voip_video_title);
		else
			mtitle.setText(R.string.voip_audio_title);
		mIv_caller = (ImageView) findViewById(R.id.basic_avatar);
		mNetworkState = (ImageView) findViewById(R.id.network_status_image);
		mCalleeName = (TextView) findViewById(R.id.callee_name);
		mRl_videopanel = (RelativeLayout) findViewById(R.id.video_call_panel);
		mRl_phoneCallingpanel = (RelativeLayout) findViewById(R.id.phone_calling_panel);
		mLl_phoneComeingPanel = (LinearLayout) findViewById(R.id.phone_coming_panel);

		mBtn_accept = (TextView) findViewById(R.id.phone_accept_calling);
		mBtn_reject = (TextView) findViewById(R.id.phone_reject_calling);
		mBtn_end = (Button) findViewById(R.id.video_drop_btn);

		mBtn_accept.setOnClickListener(this);
		mBtn_end.setOnClickListener(this);
		mBtn_reject.setOnClickListener(this);
		mll_audioCallFram = (LinearLayout) findViewById(R.id.audio_call_frame);
		mLayout_call = (FrameLayout) findViewById(R.id.call_layout);
		mCallState = (TextView) findViewById(R.id.voice_call_status);
		mtv_NetworkState = (TextView) findViewById(R.id.network_status);
		mBtn_speaker = (TextView) findViewById(R.id.phone_hands_free);
		mBtn_mute = (TextView) findViewById(R.id.phone_mute);
		mBtn_back = (TextView) findViewById(R.id.back_chat_view);
		mSwitchCamare = (TextView) findViewById(R.id.switch_camera_btn);
		mAudioClose = (Button) findViewById(R.id.audio_close);
		mBtn_phone_end = (TextView) findViewById(R.id.phone_drop_btn);
		if (!mIsvideo) {
			mBtn_speaker.setOnClickListener(this);
			mBtn_mute.setOnClickListener(this);
			mBtn_back.setOnClickListener(this);
			mBtn_phone_end.setOnClickListener(this);
		} else {
			mSwitchCamare.setOnClickListener(this);
			mVideoClose = (TextView) findViewById(R.id.video_close);
			mVideoClose.setOnClickListener(this);
		}

		// 开启或关闭声音，关闭后对方听不到自己的声音
		mAudioClose.setOnClickListener(new OnClickListener() {

			@Override
			public void onClick(View v) {
				runOnUiThread(new Runnable() {
					@Override
					public void run() {
						sendMessage("{\"type\": \"audio\"}");
					}
				});
				closeOrOpenAudio();
			}
		});

	}

	@Override
	public void onPause() {
		super.onPause();
		if (mIsvideo) {
			if (vsv != null)
				vsv.onPause();
			if (videoSource != null) {
				videoSource.stop();
			}
		}
		unregisterHomeKeyReceiver(this);
	}

	@Override
	protected void onStop() {
		// TODO Auto-generated method stub
		super.onStop();
		// Log.d("onstop", "onstop");
		runOnUiThread(new Runnable() {

			@Override
			public void run() {

				sendMessage("{\"type\": \"bye\"}");
			}
		});
	}

	@Override
	protected void onStart() {
		super.onStart();

	}

	@Override
	public void onResume() {
		super.onResume();
		if (mIsvideo) {
			if (vsv != null)
				vsv.onResume();
			if (videoSource != null) {
				videoSource.restart();
			}
		}
		registerHomeKeyReceiver(this);
	}

	/**
	 * 初始化视频链接，连接通后显示功能操作按钮
	 * 
	 * @param iceServers
	 */
	private void initPeer(List<PeerConnection.IceServer> iceServers) {
		if (mIsvideo) {
			mAudioUtil.turnOnSpeaker();
			mLocalView = ViERenderer.CreateLocalRenderer(this);
			LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(
					150, 200);
			params.gravity = Gravity.CENTER;

			mll_audioCallFram.setVisibility(View.GONE);
			mLl_phoneComeingPanel.setVisibility(View.GONE);

			// *************new****************被叫不能控制
			if (mIsCaller) {
				mRl_videopanel.setVisibility(View.VISIBLE); // new VISIBLE
			} else { // new ************VISIBLE
				mRl_videopanel.setVisibility(View.GONE);
			}
			// *************new****************
			// mRl_videopanel.setVisibility(View.VISIBLE);
			ViewStub vs = (ViewStub) findViewById(R.id.vs_video);
			View v = vs.inflate();
			vsv = (VideoStreamsView) v.findViewById(R.id.remote_view);
			mLayout_call.addView(mLocalView, 0);
			vsv.init(displaySize);
			vsv.setVisibility(View.VISIBLE);
			vsv.setOnTouchListener(new OnTouchListener() {

				@Override
				public boolean onTouch(View v, MotionEvent event) {
					// TODO Auto-generated method stub

					int visble = mRl_videopanel.getVisibility();
					if (View.GONE == visble) {
						mRl_videopanel.setVisibility(View.VISIBLE);
					} else {
						mRl_videopanel.setVisibility(View.GONE);
					}
					return false;
				}
			});

			factory = new PeerConnectionFactory();
			pc = factory.createPeerConnection(iceServers, pcConstraints,
					pcObserver);

			final PeerConnection finalPC = pc;
			final Runnable repeatedStatsLogger = new Runnable() {
				public void run() {
					synchronized (quit[0]) {
						if (quit[0]) {
							return;
						}
						final Runnable runnableThis = this;
						boolean success = finalPC.getStats(new StatsObserver() {
							public void onComplete(StatsReport[] reports) {
								for (StatsReport report : reports) {
									Log.d(TAG, "Stats: " + report.toString());
								}
								vsv.postDelayed(runnableThis, 10000);
							}
						}, null);
						if (!success) {
							throw new RuntimeException(
									"getStats() return false!");
						}
					}
				}
			};
			vsv.postDelayed(repeatedStatsLogger, 10000);

			lMS = factory.createLocalMediaStream("ARDAMS");
			if (videoConstraints != null) {

				isFrontCamare = false; // 默认开启后置摄像头
				VideoCapturer capturer = getVideoCapturer(true);

				isFrontCamare = false;// 默认改为后置摄像头
				videoSource = factory.createVideoSource(capturer,
						videoConstraints);
				VideoTrack videoTrack = factory.createVideoTrack("ARDAMSv0",
						videoSource);
				videoTrack.addRenderer(new VideoRenderer(new VideoCallbacks(
						vsv, VideoStreamsView.Endpoint.LOCAL)));

				lMS.addTrack(videoTrack);
			}
			AudioTrack audioTrack = factory.createAudioTrack("ARDAMSa0");
			audioTrack.setEnabled(isAudioOpen);
			lMS.addTrack(audioTrack);
			pc.addStream(lMS, new MediaConstraints());
		} else {
			mRl_videopanel.setVisibility(View.GONE);
			mLl_phoneComeingPanel.setVisibility(View.GONE);

			mRl_phoneCallingpanel.setVisibility(View.VISIBLE);
			factory = new PeerConnectionFactory();
			pc = factory.createPeerConnection(iceServers, pcConstraints,
					pcObserver);
			MediaStream lMS = factory.createLocalMediaStream("ARDAMS");
			lMS.addTrack(factory.createAudioTrack("ARDAMSa0"));
			pc.addStream(lMS, new MediaConstraints());
		}
		uiHandler.sendEmptyMessage(SHOW_AUDIO);
	}

	// Cycle through likely device names for the camera and return the first
	// capturer that works, or crash if none do.
	private VideoCapturer getVideoCapturer(boolean front) {

		String[] cameraFacing = (isFrontCamare) ? new String[] { "front",
				"back" } : new String[] { "back", "front" };

		// = { "back","front" };
		int[] cameraIndex = { 0, 1 };
		// int[] cameraOrientation = { 0, 90, 180, 270 };
		int[] cameraOrientation = { 0, 90, 180, 270 };

		for (String facing : cameraFacing) {
			for (int index : cameraIndex) {

				for (int orientation : cameraOrientation) {
					String name = "Camera " + index + ", Facing " + facing
							+ ", Orientation " + orientation;
					VideoCapturer capturer = VideoCapturer.create(name);
					if (capturer != null) {
						// logAndToast("Using camera: " + name);
						return capturer;
					}
				}
			}
		}

		throw new RuntimeException("Failed to open capturer");
	}

	@Override
	public void onDestroy() {
		// disconnectAndExit();
		super.onDestroy();

		unregisterReceiver(receiver);
		// ……………………………………new……一端异常退出是发送退出指令………………
		runOnUiThread(new Runnable() {

			@Override
			public void run() {

				sendMessage("{\"type\": \"bye\"}");
			}
		});

		// ………………………………

		unbindService(conn);
		EventBus.getDefault().unregister(this);
		mNotificationManager.cancel(NOTIFY_ID);

		isInit = false;

		// stopRingtone();
		if (mWakeLockUtil != null)
			mWakeLockUtil.stopProximityLock();
		mAudioUtil.destroy();
		LogUtis.log("Video destory..........");

	}

	// Poor-man's assert(): die with |msg| unless |condition| is true.
	private static void abortUnless(boolean condition, String msg) {
		if (!condition) {
			throw new RuntimeException(msg);
		}
	}

	// Put a |key|->|value| mapping in |json|.
	private static void jsonPut(JSONObject json, String key, Object value) {
		try {
			json.put(key, value);
		} catch (JSONException e) {
			throw new RuntimeException(e);
		}
	}

	// Implementation detail: observe ICE & stream changes and react
	// accordingly.
	private class PCObserver implements PeerConnection.Observer {
		@Override
		public void onIceCandidate(final IceCandidate candidate) {
			runOnUiThread(new Runnable() {
				public void run() {
					JSONObject json = new JSONObject();
					jsonPut(json, "type", "candidate");
					jsonPut(json, "label", candidate.sdpMLineIndex);
					jsonPut(json, "id", candidate.sdpMid);
					jsonPut(json, "candidate", candidate.sdp);

					sendMessage(json.toString());

				}
			});
		}

		@Override
		public void onError() {
			runOnUiThread(new Runnable() {
				public void run() {
					throw new RuntimeException("PeerConnection error!");
				}
			});
		}

		@Override
		public void onSignalingChange(PeerConnection.SignalingState newState) {
			Log.i("huazhao", "***********" + newState);
			switch (newState) {
			case STABLE:
				runOnUiThread(new Runnable() {
					public void run() {
						// mCallTimer.startTimer(VideoUI.this);
					}
				});

				break;
			case HAVE_LOCAL_OFFER:
			case HAVE_REMOTE_OFFER:
				runOnUiThread(new Runnable() {
					public void run() {
						mtv_NetworkState.setText("正在建立连接...");
					}
				});

				break;

			default:
				break;
			}
		}

		@Override
		public void onIceConnectionChange(
				PeerConnection.IceConnectionState newState) {
		}

		@Override
		public void onIceGatheringChange(
				PeerConnection.IceGatheringState newState) {
		}

		@Override
		public void onAddStream(final MediaStream stream) {

			runOnUiThread(new Runnable() {
				public void run() {
					abortUnless(stream.audioTracks.size() <= 1
							&& stream.videoTracks.size() <= 1,
							"Weird-looking stream: " + stream);
					if (stream.videoTracks.size() == 1) {
						stream.videoTracks.get(0).addRenderer(
								new VideoRenderer(new VideoCallbacks(vsv,
										VideoStreamsView.Endpoint.REMOTE)));

					}

				}
			});
		}

		@Override
		public void onRemoveStream(final MediaStream stream) {
			runOnUiThread(new Runnable() {
				public void run() {
					stream.videoTracks.get(0).dispose();
				}
			});
		}

		@Override
		public void onDataChannel(final DataChannel dc) {
			runOnUiThread(new Runnable() {
				public void run() {
					throw new RuntimeException(
							"AppRTC doesn't use data channels, but got: "
									+ dc.label() + " anyway!");
				}
			});
		}
	}

	// Implementation detail: handle offer creation/signaling and answer
	// setting,
	// as well as adding remote ICE candidates once the answer SDP is set.
	private class SDPObserver implements SdpObserver {
		@Override
		public void onCreateSuccess(final SessionDescription origSdp) {
			runOnUiThread(new Runnable() {
				public void run() {
					Log.i("zouzi", "orgsdp:" + origSdp.description);
					SessionDescription sdp = new SessionDescription(
							origSdp.type, preferISAC(origSdp.description));
					JSONObject json = new JSONObject();
					jsonPut(json, "type", sdp.type.canonicalForm());
					jsonPut(json, "sdp", sdp.description);

					sendMessage(json.toString());
					pc.setLocalDescription(sdpObserver, sdp);

				}
			});
		}

		@Override
		public void onSetSuccess() {
			runOnUiThread(new Runnable() {
				public void run() {

					if (null == pc)
						return;

					if (isInit) {
						if (pc.getRemoteDescription() != null) {
							// We've set our local offer and received & set the
							// remote
							// answer, so drain candidates.
							drainRemoteCandidates();
						}
					} else {
						if (pc.getLocalDescription() == null) {

							pc.createAnswer(SDPObserver.this,
									sdpMediaConstraints);

							// fighting mCallTimer.startTimer(VideoUI.this);

						} else {
							// Sent our answer and set it as local description;
							// drain
							// candidates.
							drainRemoteCandidates();
						}
					}
				}
			});
		}

		@Override
		public void onCreateFailure(final String error) {
			runOnUiThread(new Runnable() {
				public void run() {
					throw new RuntimeException("createSDP error: " + error);
				}
			});
		}

		@Override
		public void onSetFailure(final String error) {
			runOnUiThread(new Runnable() {
				public void run() {
					throw new RuntimeException("setSDP error: " + error);
				}
			});
		}

		private void drainRemoteCandidates() {
			for (IceCandidate candidate : queuedRemoteCandidates) {
				pc.addIceCandidate(candidate);
			}
			queuedRemoteCandidates = null;
		}
	}

	private class GAEHandler implements GAEChannelClient.MessageHandler {

		public void onOpen() {
			if (!isInit) {
				return;
			}
			if (pc != null)
				pc.createOffer(sdpObserver, sdpMediaConstraints);

		}

		public void onMessage(final String data) {
			runOnUiThread(new Runnable() {

				@Override
				public void run() {
					// TODO Auto-generated method stub

					Log.i("zouzi", "onmessage sdp:" + data);
					try {
						JSONObject json = new JSONObject(data);
						String type = (String) json.get("type");
						if (type.equals("candidate")) {
							IceCandidate candidate = new IceCandidate(
									(String) json.get("id"),
									json.getInt("label"),
									(String) json.get("candidate"));
							if (queuedRemoteCandidates != null) {
								queuedRemoteCandidates.add(candidate);
							} else {
								if (pc != null)
									pc.addIceCandidate(candidate);
							}

						} else if (type.equals("answer")
								|| type.equals("offer")) {

							SessionDescription sdp = new SessionDescription(
									SessionDescription.Type
											.fromCanonicalForm(type),
									preferISAC((String) json.get("sdp")));
							if (pc != null)
								pc.setRemoteDescription(sdpObserver, sdp);
							if (type.equals("answer")) {
								// mCallTimer.startTimer(VideoUI.this);

								isInit = true;

							}
						} else if (type.equals("bye")) {

							if (mWakeLockUtil != null)
								mWakeLockUtil.stopProximityLock();

							if (call_state == UA_STATE_INCOMING_CALL)
								call_state = UA_STATE_IDLE;

							disconnectAndExit();

						} else if (type.equals("accept")) {
							stopRingtone();
							call_state = UA_STATE_INCALL;

							isInit = true;
							if (mIsvideo
									&& Build.VERSION.SDK_INT < Build.VERSION_CODES.HONEYCOMB) {
								Toast.makeText(VideoUI.this,
										"手机os版本过低，请升级到3.0以后版本",
										Toast.LENGTH_LONG).show();
								;
								finish();
							} else
								initPeer(iceServers);
							gaeHandler.onOpen();

						} else if (type.equals("busy")) {
							Toast.makeText(VideoUI.this,
									R.string.voip_user_busy_tips,
									Toast.LENGTH_LONG).show();
							disconnectAndExit();

						} else if (type.equals("audio")) {
							closeOrOpenAudio();
						} else {
							throw new RuntimeException("Unexpected message: "
									+ data);
						}
					} catch (JSONException e) {
						throw new RuntimeException(e);
					}

				}

			});

		}

		public void onClose() {
			disconnectAndExit();
		}

		public void onError(int code, String description) {
			disconnectAndExit();
		}
	}

	private void disconnectAndExit() {

		synchronized (quit[0]) {
			if (quit[0]) {
				return;
			}
			quit[0] = true;
			wakeLock.release();
			if (pc != null) {
				pc.dispose();
				pc = null;
			}

			if (videoSource != null) {
				videoSource.dispose();
				videoSource = null;
			}
			if (factory != null) {
				factory.dispose();
				factory = null;
			}
			finish();
		}
	}

	// Implementation detail: bridge the VideoRenderer.Callbacks interface to
	// the
	// VideoStreamsView implementation.
	private class VideoCallbacks implements VideoRenderer.Callbacks {
		private final VideoStreamsView view;
		private final VideoStreamsView.Endpoint stream;

		public VideoCallbacks(VideoStreamsView view,
				VideoStreamsView.Endpoint stream) {
			this.view = view;
			this.stream = stream;

		}

		@Override
		public void setSize(final int width, final int height) {
			view.queueEvent(new Runnable() {
				public void run() {
					view.setSize(stream, width, height);
				}
			});
		}

		@Override
		public void renderFrame(I420Frame frame) {

			view.queueFrame(stream, frame);
		}
	}

	// Mangle SDP to prefer ISAC/16000 over any other audio codec.
	private String preferISAC(String sdpDescription) {
		String[] lines = sdpDescription.split("\n");
		int mLineIndex = -1;
		String isac16kRtpMap = null;
		Pattern isac16kPattern = Pattern
				.compile("^a=rtpmap:(\\d+) ILBC/8000[\r]?$");
		for (int i = 0; (i < lines.length)
				&& (mLineIndex == -1 || isac16kRtpMap == null); ++i) {
			if (lines[i].startsWith("m=audio ")) {
				mLineIndex = i;
				continue;
			}
			Matcher isac16kMatcher = isac16kPattern.matcher(lines[i]);
			if (isac16kMatcher.matches()) {
				isac16kRtpMap = isac16kMatcher.group(1);
				continue;
			}
		}
		if (mLineIndex == -1) {
			Log.d(TAG, "No m=audio line, so can't prefer iSAC");
			return sdpDescription;
		}
		if (isac16kRtpMap == null) {
			Log.d(TAG, "No ISAC/16000 line, so can't prefer iSAC");
			return sdpDescription;
		}
		String[] origMLineParts = lines[mLineIndex].split(" ");
		StringBuilder newMLine = new StringBuilder();
		int origPartIndex = 0;
		// Format is: m=<media> <port> <proto> <fmt> ...
		newMLine.append(origMLineParts[origPartIndex++]).append(" ");
		newMLine.append(origMLineParts[origPartIndex++]).append(" ");
		newMLine.append(origMLineParts[origPartIndex++]).append(" ");
		newMLine.append(isac16kRtpMap).append(" ");
		for (; origPartIndex < origMLineParts.length; ++origPartIndex) {
			if (!origMLineParts[origPartIndex].equals(isac16kRtpMap)) {
				newMLine.append(origMLineParts[origPartIndex]).append(" ");
			}
		}
		lines[mLineIndex] = newMLine.toString();
		StringBuilder newSdpDescription = new StringBuilder();
		for (String line : lines) {
			newSdpDescription.append(line).append("\n");
		}
		return newSdpDescription.toString();
	}

	public void stopRingtone() {

		if (mAudioUtil != null) {
			mAudioUtil.stopRingtone();
			mAudioUtil.stop();
			mAudioUtil.setSpeakOff();
		}

	}

	@Override
	public void onClick(View v) {
		switch (v.getId()) {
		// 关闭
		case R.id.phone_drop_btn:
		case R.id.video_drop_btn:
			// stopRingtone();
			runOnUiThread(new Runnable() {

				@Override
				public void run() {

					sendMessage("{\"type\": \"bye\"}");
				}
			});

			disconnectAndExit();

			break;

		// 拒接
		case R.id.phone_reject_calling:
			// stopRingtone();
			// call_state = UA_STATE_REJECT;
			runOnUiThread(new Runnable() {

				@Override
				public void run() {

					sendMessage("{\"type\": \"bye\"}");
				}
			});

			disconnectAndExit();

			break;
		// 接听
		case R.id.phone_accept_calling:

			// mServiceAdapter.clearNotifications(mWithJabberID);
			// stopRingtone();

			call_state = UA_STATE_INCALL;
			runOnUiThread(new Runnable() {

				@Override
				public void run() {

					sendMessage("{\"type\": \"accept\"}");
				}
			});

			gaeHandler.onOpen();
			if (mIsvideo
					&& Build.VERSION.SDK_INT < Build.VERSION_CODES.HONEYCOMB) {
				Toast.makeText(this, "手机os版本过低，请升级到3.0以后版本", Toast.LENGTH_LONG)
						.show();
				finish();
			} else
				initPeer(iceServers);
			break;
		// 扬声器
		case R.id.phone_hands_free:
			toggleAudio();
			break;

		case R.id.phone_mute:

			break;

		// 开启关闭摄像头
		case R.id.video_close:
			closeOrOpenVideo();// 开启关闭摄像头
			break;
		case R.id.switch_camera_btn:
			// logAndToast("切换视频");
			isFrontCamare = !isFrontCamare;
			switchCapter();

			break;

		default:
			break;
		}

	}

	/**
	 * 开启关闭声音
	 */
	private void closeOrOpenAudio() {

		mHandler.post(new Runnable() {
			@Override
			public void run() {
				// TODO Auto-generated method stub
				isAudioOpen = !isAudioOpen;
				AudioTrack audioTrack = lMS.audioTracks.peek();
				audioTrack.setEnabled(isAudioOpen);
				uiHandler.sendEmptyMessage(SHOW_AUDIO);
			}
		});

	}

	private void closeOrOpenVideo() {

		mHandler.post(new Runnable() {

			@Override
			public void run() {
				// TODO Auto-generated method stub
				if (lMS != null) {

					pc.removeStream(lMS);

					lMS.dispose();

				}

				// if (videoSource != null) {
				// videoSource.stop();
				// videoSource.dispose();
				// }
				lMS = factory.createLocalMediaStream("ARDAMS");

				if (isVideoOpen) {
					vsv.isClose = true;
					mVideoClose.setText("打开摄像头");
					vsv.onResume();
				} else {
					mVideoClose.setText("关闭摄像头");
					vsv.isClose = false;
					vsv.onResume();
					videoSource.dispose();
					VideoCapturer capturer = getVideoCapturer(true);

					videoSource = factory.createVideoSource(capturer,
							videoConstraints);

					VideoTrack videoTrack = factory.createVideoTrack(
							"ARDAMSv0", videoSource);

					videoTrack.addRenderer(new VideoRenderer(
							new VideoCallbacks(vsv,
									VideoStreamsView.Endpoint.LOCAL)));

					lMS.addTrack(videoTrack);
				}

				AudioTrack audioTrack = factory.createAudioTrack("ARDAMSa0");
				lMS.addTrack(audioTrack);

				pc.addStream(lMS, new MediaConstraints());
				isVideoOpen = !isVideoOpen;
			}
		});

	}

	private void switchCapter() {
		if (lMS != null) {

			pc.removeStream(lMS);

			lMS.dispose();
		}
		if (videoSource != null) {
			videoSource.stop();
			videoSource.dispose();
		}
		lMS = factory.createLocalMediaStream("ARDAMS");

		VideoCapturer capturer = getVideoCapturer(true);

		videoSource = factory.createVideoSource(capturer, videoConstraints);

		VideoTrack videoTrack = factory.createVideoTrack("ARDAMSv0",
				videoSource);

		videoTrack.addRenderer(new VideoRenderer(new VideoCallbacks(vsv,
				VideoStreamsView.Endpoint.LOCAL)));

		lMS.addTrack(videoTrack);

		AudioTrack audioTrack = factory.createAudioTrack("ARDAMSa0");
		lMS.addTrack(audioTrack);

		pc.addStream(lMS, new MediaConstraints());

	}

	@Override
	public void onAudioChange() {
		// TODO Auto-generated method stub
		if (mAudioUtil.isSpeakerOn()) {
			Drawable d = getResources().getDrawable(
					R.drawable.phone_icon_hands_free_02);
			mBtn_speaker.setCompoundDrawablesWithIntrinsicBounds(null, d, null,
					null);
			if (mWakeLockUtil != null)
				mWakeLockUtil.stopProximityLock();
		} else {
			Drawable d = getResources().getDrawable(
					R.drawable.phone_icon_hands_free_01);
			mBtn_speaker.setCompoundDrawablesWithIntrinsicBounds(null, d, null,
					null);
			if (mWakeLockUtil != null)
				mWakeLockUtil.startProximityLock();
		}

	}

	/**
	 *  
	 */
	private void toggleAudio() {
		if (mAudioUtil.isSpeakerOn()) {
			if (mAudioUtil.wiredHeadsetEnabled()) {
				mAudioUtil.turnOnWiredHeadset();
			} else {
				mAudioUtil.turnOnHeadset();
			}
		} else {
			mAudioUtil.turnOnSpeaker();

		}
	}

	/**
	 * 亮屏解锁
	 */
	private void openLock() {
		PowerManager powerManager = (PowerManager) getSystemService(POWER_SERVICE);
		wakeLock = powerManager.newWakeLock(PowerManager.ACQUIRE_CAUSES_WAKEUP
				| PowerManager.SCREEN_DIM_WAKE_LOCK, "Hisuper");
		wakeLock.acquire();
		mKManager = (KeyguardManager) getSystemService(Context.KEYGUARD_SERVICE);
		// 得到键盘锁管理器对象
		mKeyguardLock = mKManager.newKeyguardLock("unLock");
		// 参数是LogCat里用的Tag
		mKeyguardLock.disableKeyguard();
	}

	public static void setCameraDisplayOrientation(Activity activity,
			int cameraId, android.hardware.Camera camera) {
		android.hardware.Camera.CameraInfo info = new android.hardware.Camera.CameraInfo();
		android.hardware.Camera.getCameraInfo(cameraId, info);
		int rotation = activity.getWindowManager().getDefaultDisplay()
				.getRotation();
		int degrees = 0;

		switch (rotation) {
		case Surface.ROTATION_0:
			degrees = 0;
			break;
		case Surface.ROTATION_90:
			degrees = 90;
			break;
		case Surface.ROTATION_180:
			degrees = 180;
			break;
		case Surface.ROTATION_270:
			degrees = 270;
			break;
		}
		int result;
		if (info.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) {
			result = (info.orientation + degrees) % 360;
			result = (360 - result) % 360; // compensate the mirror
		} else {
			// back-facing
			result = (info.orientation - degrees + 360) % 360;
		}
		camera.setDisplayOrientation(result);
	}

	// public boolean dispatchKeyEvent(KeyEvent event) {
	// System.out.println("key:" + event.getKeyCode());
	// if (event.getKeyCode() == KeyEvent.KEYCODE_BACK) {
	// if (event.getAction() == KeyEvent.ACTION_DOWN
	// && event.getRepeatCount() == 0) {
	//
	// // 要执行的事件
	// this.moveTaskToBack(true);
	// }
	// return true;
	// }
	// return super.dispatchKeyEvent(event);
	// }

	private MyServiceConnection conn = new MyServiceConnection();

	private class MyServiceConnection implements
			android.content.ServiceConnection {

		@Override
		public void onServiceConnected(ComponentName name, IBinder service) {
			mClient = (ISocketClient) service;
			if (mIsCaller) {
				sendMessage("{\"type\": \"phone\",\"isvideo\": \"true\"}");
				LogUtis.log("call to :" + mUid);
			} else {

				sendMessage("{\"type\": \"accept\"}");
				gaeHandler.onOpen();
				if (mIsvideo
						&& Build.VERSION.SDK_INT < Build.VERSION_CODES.HONEYCOMB) {
					Toast.makeText(VideoUI.this, "手机os版本过低，请升级到3.0以后版本",
							Toast.LENGTH_LONG).show();
					finish();
				} else
					initPeer(iceServers);

			}

		}

		@Override
		public void onServiceDisconnected(ComponentName name) {
			// TODO Auto-generated method stub
			mClient = null;
		}

	}

	private void bindService() {
		Intent serviceIntent = new Intent(this, MessageService.class);
		bindService(serviceIntent, conn, BIND_AUTO_CREATE);
	}

	public void sendMessage(String string) {
		if (mClient != null) {
			mClient.sendPhoneMessage(mUid, string);
		}

	}

	private void registerEvent() {
		EventBus.getDefault().register(this, "onMessage", Message.class);
	}

	public void onMessage(final Message message) {

		switch (message.getType()) {
		case PHONE:
			gaeHandler.onMessage(message.getContent());
			break;

		default:
			break;
		}
	}

	private void registerBroadcast() {
		IntentFilter filter = new IntentFilter(Constants.LOGIN_OTHER);
		registerReceiver(receiver, filter);
	}

	/**
	 * home键监听
	 * 
	 * @see 如果在通话中按下home键,则在com.bieyang.anjia.utils.HomeWatcherReceiver结束当前通话
	 *      使用说明：onResume中调用registerHomeKeyReceiver，
	 *      onPause中调用unregisterHomeKeyReceiver
	 */
	private static HomeWatcherReceiver mHomeKeyReceiver = null;

	private static void registerHomeKeyReceiver(Context context) {
		// Log.i(LOG_TAG, "registerHomeKeyReceiver");
		mHomeKeyReceiver = new HomeWatcherReceiver();
		final IntentFilter homeFilter = new IntentFilter(
				Intent.ACTION_CLOSE_SYSTEM_DIALOGS);

		context.registerReceiver(mHomeKeyReceiver, homeFilter);
	}

	private static void unregisterHomeKeyReceiver(Context context) {
		// Log.i(LOG_TAG, "unregisterHomeKeyReceiver");
		if (null != mHomeKeyReceiver) {
			context.unregisterReceiver(mHomeKeyReceiver);
		}
	}

	// @Override
	// public boolean onKeyDown(int keyCode, KeyEvent event) {
	// // TODO Auto-generated method stub
	// Log.d("keyCode", ""+keyCode);
	// if(keyCode==KeyEvent.KEYCODE_BACK || keyCode==KeyEvent.KEYCODE_HOME){
	// // unregisterReceiver(receiver);
	// // ……………………………………new……按home键或返回键时发送退出指令………………
	// runOnUiThread(new Runnable() {
	//
	// @Override
	// public void run() {
	//
	// sendMessage("{\"type\": \"bye\"}");
	// }
	// });
	//
	// return true;
	// }
	// return super.onKeyDown(keyCode, event);
	// }

}
